/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package afterubuntu.google;

import afterubuntu.log.Log;
import afterubuntu.pojo.APTPackage;
import afterubuntu.pojo.AfterUbuntuData;
import afterubuntu.pojo.Application;
import afterubuntu.pojo.AutConfiguration;
import afterubuntu.pojo.Category;
import afterubuntu.pojo.CmdConfiguration;
import afterubuntu.pojo.DEBPackage;
import afterubuntu.pojo.GPARepository;
import afterubuntu.pojo.GetConfiguration;
import afterubuntu.pojo.IcoConfiguration;
import afterubuntu.pojo.PPARepository;
import afterubuntu.pojo.REMPackage;
import afterubuntu.pojo.RepositoryKey;
import afterubuntu.pojo.ZipConfiguration;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

/**
 *
 * @author Kermit
 */
public class GoogleManager implements Runnable{

    public static final int ERROR = -1;
    public static final int OK = 0;
    public static final int BAD_CREDENTIALS = 1;
    public static final int SPREADSHEET_NOT_FOUND = 2;
    public static final int MORE_THAN_ONE_SPREADSHEET = 3;
    public static final int WORKSHEET_NOT_FOUND = 4;

    private static final String TAG_CATEGORY = "category";
    private static final String TAG_APP_DESCRIPTION = "description";
    private static final String TAG_APP_REPOSITORY = "repositories";
    private static final String TAG_APP_PACKAGE = "packages";
    private static final String TAG_APP_CONFIGURATION = "config";
    private static final String TAG_APP_USER = "user";
    private static final String TAG_APP_COMMENT = "comment";

    private SpreadsheetService client;
    private SpreadsheetEntry spreadsheetEntry;
    private WorksheetEntry worksheetEntry;

    private GoogleManagerListener googleManagerListener;

    private String gUsername;
    private String gPassword;
    private String spreadsheet;
    private String worksheet;

    private String URL_BASE;

    public GoogleManager(){
        this.spreadsheetEntry = null;
        this.worksheetEntry = null;
        this.googleManagerListener = null;
    }

    public void setWorksheetData(String gUsername, String gPassword, String spreadsheet, String worksheet){
        this.gUsername = gUsername;
        this.gPassword = gPassword;
        this.spreadsheet = spreadsheet;
        this.worksheet = worksheet;
    }

    public AfterUbuntuData parseWorksheet() {

        try{
            AfterUbuntuData afterUbuntuData = new AfterUbuntuData();

            URL listFeedUrl = worksheetEntry.getListFeedUrl();
            ListFeed feed = client.getFeed(listFeedUrl, ListFeed.class);
            for (ListEntry entry : feed.getEntries()) {
                String categoryName = entry.getCustomElements().getValue(GoogleManager.TAG_CATEGORY);
                if(categoryName.equalsIgnoreCase("Metadata")){
                    URL_BASE = entry.getCustomElements().getValue(GoogleManager.TAG_APP_DESCRIPTION).split("=")[1];
                    continue;
                }
                Application application = createApplication(entry);
                Category category = afterUbuntuData.getCategory(categoryName);
                if(category == null){
                    category = new Category();
                    category.setName(categoryName);
                    category.addApplication(application);
                    afterUbuntuData.addCategory(category);
                }else{
                    category.addApplication(application);
                }
            }
            return afterUbuntuData;
        } catch (IOException ioe){
            Log.getInstance().log(Log.ERROR, ioe.getLocalizedMessage());
        } catch (ServiceException se){
            Log.getInstance().log(Log.ERROR, se.getLocalizedMessage());
        }

        return null;
    }

    private Application createApplication(ListEntry entry) {

        Application application = new Application();

        String appDescription = entry.getCustomElements().getValue(GoogleManager.TAG_APP_DESCRIPTION);
        application.setDescription(appDescription);
        String appRespositories = entry.getCustomElements().getValue(TAG_APP_REPOSITORY);
        if(appRespositories != null){
            setRepositoriesAndKeys(appRespositories, application);
        }
        String appPackages = entry.getCustomElements().getValue(TAG_APP_PACKAGE);
        if(appPackages != null){
            setPackages(appPackages, application);
        }
        String appConfiguration = entry.getCustomElements().getValue(TAG_APP_CONFIGURATION);
        if(appConfiguration != null){
            setConfigurations(appConfiguration, application);
        }
        String appUser = entry.getCustomElements().getValue(TAG_APP_USER);
        if(appUser != null){
            setUser(appUser, application);
        }
        String appComment = entry.getCustomElements().getValue(TAG_APP_COMMENT);
        if(appComment != null){
            setComment(appComment, application);
        }

        application.setInstall(true);
        return application;

    }

    public void addListener(GoogleManagerListener googleManagerListener) {
        this.googleManagerListener = googleManagerListener;
    }

    public void run() {
        try {
            client = new SpreadsheetService("AfterUbuntu");
            client.setUserCredentials(gUsername, gPassword);
            Log.getInstance().log(Log.INFO, "Connecting to '" + gUsername + "' Google account");
            URL feedUri = new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full");
            Log.getInstance().log(Log.INFO, "Connected to '" + gUsername + "' Google account");
            SpreadsheetQuery query = new SpreadsheetQuery(feedUri);
            query.setSortMode("title");
            query.setTitleQuery(spreadsheet);
            query.setTitleExact(true);
            query.setMaxResults(2);
            Log.getInstance().log(Log.INFO, "Getting spreadsheet '" + spreadsheet + "'");
            SpreadsheetFeed feed = client.getFeed(query, SpreadsheetFeed.class);
            List<SpreadsheetEntry> spreadsheetEntries = feed.getEntries();
            if(spreadsheetEntries == null || spreadsheetEntries.isEmpty()){
                Log.getInstance().log(Log.ERROR, "No spreadsheet named '" + spreadsheet + "' found");
                if(googleManagerListener != null){
                    googleManagerListener.requestComplete(GoogleManager.SPREADSHEET_NOT_FOUND);
                    return;
                }
            }
            if(spreadsheetEntries.size() > 1){
                Log.getInstance().log(Log.ERROR, "More than one spreadsheet named '" + spreadsheet + "'");
                if(googleManagerListener != null){
                    googleManagerListener.requestComplete(GoogleManager.MORE_THAN_ONE_SPREADSHEET);
                    return;
                }
            }
            spreadsheetEntry= spreadsheetEntries.get(0);
            Log.getInstance().log(Log.INFO, "Spreadsheet '" + spreadsheet + "' found");
            Log.getInstance().log(Log.INFO, "Getting worksheet '" + worksheet + "' on spreadsheet '" + spreadsheet + "'");
            List<WorksheetEntry> worksheetEntries = spreadsheetEntry.getWorksheets();
            for(WorksheetEntry worksheetEntryAux : worksheetEntries){
                if(worksheetEntryAux.getTitle().getPlainText().equals(worksheet)){
                    worksheetEntry = worksheetEntryAux;
                    Log.getInstance().log(Log.INFO, "Worksheet '" + worksheet + "' on spreadsheet '" + spreadsheet + "' found");
                    break;
                }
            }
            if(worksheetEntry == null){
                Log.getInstance().log(Log.ERROR, "No worksheet named '" + worksheet + "' found on spreadsheet '" + spreadsheet + "'");
                if(googleManagerListener != null){
                    googleManagerListener.requestComplete(GoogleManager.WORKSHEET_NOT_FOUND);
                    return;
                }
            }

            if(googleManagerListener != null) googleManagerListener.requestComplete(GoogleManager.OK);

            } catch (AuthenticationException ae){
                Log.getInstance().log(Log.ERROR, "Google authentication error");
                if(googleManagerListener != null) googleManagerListener.requestComplete(GoogleManager.BAD_CREDENTIALS);
            } catch (MalformedURLException mue){
                Log.getInstance().log(Log.ERROR, mue.getLocalizedMessage());
                if(googleManagerListener != null) googleManagerListener.requestComplete(GoogleManager.ERROR);
            } catch (ServiceException se){
                Log.getInstance().log(Log.ERROR, se.getLocalizedMessage());
                if(googleManagerListener != null) googleManagerListener.requestComplete(GoogleManager.ERROR);
            } catch (IOException ioe){
                Log.getInstance().log(Log.ERROR, ioe.getLocalizedMessage());
                if(googleManagerListener != null) googleManagerListener.requestComplete(GoogleManager.ERROR);
            }
    }

    private void setRepositoriesAndKeys(String appRespositories, Application application) {

        String[] repositories = appRespositories.split("#");
        for(int i = 0; i < repositories.length; i++){
            if(repositories[i].startsWith("rep")){
                String rep = repositories[i].substring(repositories[i].indexOf("(")+1, repositories[i].indexOf(")"));
                String repData[] = rep.split(",");
                GPARepository gpaRepository = new GPARepository();
                gpaRepository.setName(repData[0]);
                gpaRepository.setRepository(repData[1]);
                application.addGPARepository(gpaRepository);
            }
            if(repositories[i].startsWith("ppa")){
                String rep = repositories[i].substring(repositories[i].indexOf("(")+1, repositories[i].indexOf(")"));
                String name;
                int index = rep.indexOf("/");
                if(index == -1) name = rep;
                else name = rep.substring(0, index);
                PPARepository ppaRepository = new PPARepository();
                ppaRepository.setName(name);
                ppaRepository.setRepository(rep);
                application.addPPARepository(ppaRepository);
            }
            if(repositories[i].startsWith("key")){
                String rep = repositories[i].substring(repositories[i].indexOf("(")+1, repositories[i].indexOf(")"));
                RepositoryKey repositoryKey = new RepositoryKey();
                repositoryKey.setKey(rep);
                application.addRepositoryKey(repositoryKey);
            }
        }

    }

    private void setPackages(String appPackages, Application application) {

        String[] packages = appPackages.split("#");
        for(int i = 0; i < packages.length; i++){
            if(packages[i].startsWith("apt")){
                String pack = packages[i].substring(packages[i].indexOf("(")+1, packages[i].indexOf(")"));
                String[] packs = pack.split(" ");
                APTPackage aptPackage = new APTPackage();
                for(int j = 0; j < packs.length; j++){
                    aptPackage.addAPTPackage(packs[j]);
                }
                application.addAPTPackage(aptPackage);
            }
            if(packages[i].startsWith("deb")){
                String pack = packages[i].substring(packages[i].indexOf("(")+1, packages[i].indexOf(")"));
                String[] packs = pack.split(" ");
                DEBPackage debPackage = new DEBPackage();
                for(int j = 0; j < packs.length; j++){
                    packs[j] = packs[j].replace("$URL_BASE", URL_BASE);
                    debPackage.addDEBPackage(packs[j]);
                }
                application.addDEBPackage(debPackage);
            }
            if(packages[i].startsWith("rem")){
                String pack = packages[i].substring(packages[i].indexOf("(")+1, packages[i].indexOf(")"));
                String[] packs = pack.split(" ");
                REMPackage remPackage = new REMPackage();
                for(int j = 0; j < packs.length; j++){
                    remPackage.addREMPackage(packs[j]);
                }
                application.addREMPackage(remPackage);
            }
        }
    }

    private void setConfigurations(String appConfiguration, Application application) {
        String[] config = appConfiguration.split("#");
        for(int i = 0; i < config.length; i++){
            if(config[i].startsWith("zip")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                String[] zipData = conf.split(",");
                ZipConfiguration zipConfiguration = new ZipConfiguration();
                zipData[0] = zipData[0].replace("$URL_BASE", URL_BASE);
                zipConfiguration.setZipFile(zipData[0]);
                if(zipData.length < 2){
                    zipConfiguration.setDirectory("$HOME");
                }else{
                    zipConfiguration.setDirectory(zipData[1]);
                }
                application.addZipConfigurations(zipConfiguration);
            }
            if(config[i].startsWith("cmd")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                CmdConfiguration cmdConfiguration = new CmdConfiguration();
                cmdConfiguration.setCommand(conf);
                application.addCmdConfiguration(cmdConfiguration);
            }
            if(config[i].startsWith("get")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                String[] getData = conf.split(",");
                GetConfiguration getConfiguration = new GetConfiguration();
                getData[0] = getData[0].replace("$URL_BASE", URL_BASE);
                getConfiguration.setUrl(getData[0]);
                getConfiguration.setDirectory(getData[1]);
                application.addGetConfiguration(getConfiguration);
            }
            if(config[i].startsWith("ico")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                IcoConfiguration icoConfiguration = new IcoConfiguration();
                conf = conf.replace("$URL_BASE", URL_BASE);
                icoConfiguration.setUrl(conf);
                application.addIcoConfiguration(icoConfiguration);
            }
            if(config[i].startsWith("aut")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                AutConfiguration autConfiguration = new AutConfiguration();
                conf = conf.replace("$URL_BASE", URL_BASE);
                autConfiguration.setUrl(conf);
                application.addAutConfiguration(autConfiguration);
            }
        }
    }

    private void setUser(String appUser, Application application) {
        String[] config = appUser.split("#");
        for(int i = 0; i < config.length; i++){
            if(config[i].startsWith("zip")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                String[] zipData = conf.split(",");
                ZipConfiguration zipConfiguration = new ZipConfiguration();
                zipData[0] = zipData[0].replace("$URL_BASE", URL_BASE);
                zipConfiguration.setZipFile(zipData[0]);
                if(zipData.length < 2){
                    zipConfiguration.setDirectory("$HOME");
                }else{
                    zipConfiguration.setDirectory(zipData[1]);
                }
                application.addZipUser(zipConfiguration);
            }
            if(config[i].startsWith("cmd")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                CmdConfiguration cmdConfiguration = new CmdConfiguration();
                cmdConfiguration.setCommand(conf);
                application.addCmdUser(cmdConfiguration);
            }
            if(config[i].startsWith("get")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                String[] getData = conf.split(",");
                GetConfiguration getConfiguration = new GetConfiguration();
                getData[0] = getData[0].replace("$URL_BASE", URL_BASE);
                getConfiguration.setUrl(getData[0]);
                getConfiguration.setDirectory(getData[1]);
                application.addGetUser(getConfiguration);
            }
            if(config[i].startsWith("ico")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                IcoConfiguration icoConfiguration = new IcoConfiguration();
                conf = conf.replace("$URL_BASE", URL_BASE);
                icoConfiguration.setUrl(conf);
                application.addIcoUser(icoConfiguration);
            }
            if(config[i].startsWith("aut")){
                String conf = config[i].substring(config[i].indexOf("(")+1, config[i].indexOf(")"));
                AutConfiguration autConfiguration = new AutConfiguration();
                conf = conf.replace("$URL_BASE", URL_BASE);
                autConfiguration.setUrl(conf);
                application.addAutUser(autConfiguration);
            }
        }
    }

    private void setComment(String appComment, Application application) {
        application.setComment(appComment);
    }

}
